package com.zbest.component.dal.sequence;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 默认的sequence实现，目前都是单数据源的
 *
 * @author czhou3306
 * @version $Id: DefaultSequence.java, v 0.1 2014-11-30 下午5:24:44 czhou3306 Exp $
 */
public class DefaultSequence implements Sequence {
    private final Lock lock = new ReentrantLock();

    private SequenceDao sequenceDao;

    /**
     * 序列名称
     */
    private String seqName;

    private volatile SequenceRange currentRange;

    public DefaultSequence(SequenceDao sequenceDao, String seqName) {
        this.sequenceDao = sequenceDao;
        this.seqName = seqName;
    }

    public long nextValue() throws SequenceException {
        return nextValue(1);
    }

    public long nextValue(long delta) throws SequenceException {
        if (currentRange == null) {
            lock.lock();
            try {
                if (currentRange == null) {
                    currentRange = sequenceDao.nextRange(seqName);
                }
            } finally {
                lock.unlock();
            }
        }

        long value = currentRange.getAndAdd(delta);
        if (value == -1) {
            lock.lock();
            try {
                for (; ; ) {
                    if (currentRange.isOver()) {
                        currentRange = sequenceDao.nextRange(seqName);
                    }

                    value = currentRange.getAndAdd(delta);
                    if (value == -1) {
                        continue;
                    }

                    break;
                }
            } finally {
                lock.unlock();
            }
        }

        if (value < 0) {
            throw new SequenceException("Sequence value overflow, value = " + value);
        }

        return value;
    }

}
